package com.linkoog.devtools.http.toolwindow.workbenche.left.http_service;

import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.linkoog.devtools.http.raw_index.HttpServiceClass;
import com.linkoog.devtools.http.raw_index.HttpServiceClassRawFileIndex;
import com.linkoog.devtools.http.raw_index.HttpServiceMethod;
import com.linkoog.devtools.http.raw_index.HttpServiceMethodRawFileIndex;
import com.linkoog.devtools.http.toolwindow.workbenche.left.http_service.node.ClassTreeNode;
import com.linkoog.devtools.http.toolwindow.workbenche.left.http_service.node.MethodTreeNode;
import com.linkoog.devtools.http.toolwindow.workbenche.left.http_service.node.ModuleTreeNode;
import com.linkoog.devtools.http.toolwindow.workbenche.left.http_service.node.PackageTreeNode;
import org.apache.commons.collections.list.TreeList;
import org.jetbrains.annotations.NotNull;

import javax.swing.tree.DefaultMutableTreeNode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class HttpServiceTreeDataProvider {

    private final Project project;

    private List<String> selectedModuleNameList = new ArrayList<>();

    public HttpServiceTreeDataProvider(Project project){
        this.project = project;
        this.selectedModuleNameList = new ArrayList<>();
        Module[] modules = ModuleManager.getInstance(project).getModules();
        for (Module module : modules) {
            selectedModuleNameList.add(module.getName());
        }
    }


    public DefaultMutableTreeNode buildHttpServiceData(){
        return ReadAction.compute(() -> buildTreeModuleNode(project));
    }

    public void resetSelectedModuleList(List<String> selectedModuleNameList){
        this.selectedModuleNameList.clear();
        if (selectedModuleNameList != null && !selectedModuleNameList.isEmpty()){
            this.selectedModuleNameList.addAll(selectedModuleNameList);
        }
    }

    private DefaultMutableTreeNode buildTreeModuleNode(Project project){
        DefaultMutableTreeNode root = new DefaultMutableTreeNode();
        Module[] modules = ModuleManager.getInstance(project).getModules();
        for (Module module : modules) {
            // 设置Module节点的数据
            if (selectedModuleNameList.contains(module.getName())){
                ModuleTreeNode moduleTreeNode = new ModuleTreeNode(module.getModuleFilePath(), module.getName(), null);
                buildTreeClassNode(project, moduleTreeNode);
                root.add(moduleTreeNode);
            }
        }
        return root;
    }

    private void buildTreeClassNode(Project project, ModuleTreeNode moduleTreeNode){
        Map<String, List<ClassTreeNode>> dataMap = new TreeMap<>();
        HttpServiceClassRawFileIndex httpServiceClassRawFileIndex = HttpServiceClassRawFileIndex.getInstance(project);
        for (HttpServiceClass httpServiceClass : httpServiceClassRawFileIndex.getCaches()) {
            if (moduleTreeNode.getModuleFilePath().equals(httpServiceClass.getModuleFilePath())){
                List<ClassTreeNode> list = dataMap.computeIfAbsent(httpServiceClass.getPackageName(), k -> new ArrayList<>());
                ClassTreeNode classTreeNode = new ClassTreeNode(httpServiceClass, httpServiceClass.getShortName(), null);
                list.add(classTreeNode);
            }
        }

        for (String packageName : dataMap.keySet()) {
            List<ClassTreeNode> list = dataMap.get(packageName);
            if (!list.isEmpty()){
                list.sort((node1, node2) -> node1.getName().compareToIgnoreCase(node2.getName()));
                PackageTreeNode packageTreeNode = new PackageTreeNode(packageName, null);
                moduleTreeNode.add(packageTreeNode);
                for (ClassTreeNode classTreeNode : list) {
                    packageTreeNode.add(classTreeNode);
                    loadTreeMethodNode(project, classTreeNode);
                }
            }
        }
    }

    private void loadTreeMethodNode(Project project, ClassTreeNode classTreeNode){
        PsiClass psiClass = classTreeNode.getHttpServiceClass().getPsiElement();
        HttpServiceMethodRawFileIndex httpServiceMethodRawFileIndex = HttpServiceMethodRawFileIndex.getInstance(project);
        final PsiMethod[] psiMethods = psiClass.getAllMethods();
        for (PsiMethod psiMethod : psiMethods) {
            HttpServiceMethod httpServiceMethod = httpServiceMethodRawFileIndex.getCache(psiMethod);
            if (httpServiceMethod != null){
                MethodTreeNode methodTreeNode = new MethodTreeNode(httpServiceMethod, psiMethod.getName(), null);
                classTreeNode.add(methodTreeNode);
            }
        }
    }

}
